package de.fhffm.gärtnerei.gui;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;

import de.fhffm.gärtnerei.exceptions.InputException;
import de.fhffm.gärtnerei.tabellen.Aussaat;
import de.fhffm.gärtnerei.tabellen.Bewaesserung;

public class BewaesserungFenster implements ActionListener{

	private Double bewaesserungsMenge = 0.0;
	
	private String bewaesserungsMengeString = null;
	private String datum = null;
	private String vorherigesDatum = null;
	private String aussaatDatum = null;
	
	private JTextField txtBewaesserungsMenge = new JTextField(8);
	
	private JFormattedTextField txtDatum ;
	
	private JLabel lblBewaesserungsMenge = new JLabel("Bewässerungs Menge");
	private JLabel lblDatum	= new JLabel("Datum");
	private JLabel infoLabel = new JLabel();
	
	private JButton btnSpeichern = new JButton("Speichern");
	private JButton btnAbbrechen = new JButton("Abbrechen");
	
	private JPanel eingabePanel = new JPanel(new GridLayout(2,2));
	private JPanel buttonPanel = new JPanel();
	private JPanel infoPanel = new JPanel();
	
	private JFrame bewaesserungsFrame = new JFrame();
	
	private List<String> ausgewaehlteZeile;
	
	private StringBuilder sb = new StringBuilder();
	
	private MaskFormatter datumFormat= null;
	
	private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy");
	
	private Date aktuellesDatum = new Date();
	private Date aussaatDate;
	private Date eingegebenesDatum ;
	
	private int bewaesserungID;
	
	private boolean bewaesserungVorhanden = false;
	
	private Bewaesserung bewaesserung = new Bewaesserung();
	
	BewaesserungFenster(List<String> ausgewaehlteZeile){
		
		this.ausgewaehlteZeile = ausgewaehlteZeile;
		
		bewaesserungsFrame.setSize(400,500);
		bewaesserungsFrame.setLocationRelativeTo(null);
		bewaesserungsFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		bewaesserungsFrame.setVisible(true);
		bewaesserungsFrame.setResizable(true);
		bewaesserungsFrame.setLayout(new BorderLayout());
		bewaesserungsFrame.setTitle("Bewässerung festlegen");
		sb.append("<html>Bewässerung für die Pflanze: '").append(ausgewaehlteZeile.get(2)).append("'");
		sb.append("<br>").append("Aus der Aussaat mit der ID: ").append(ausgewaehlteZeile.get(0)).append(" festlegen.<br><br>");
		
		ueberpruefeBewaesserung();

		infoLabel.setText(sb.toString());
		infoPanel.add(infoLabel);
		sb.setLength(0);
		
		eingabePanel.add(lblBewaesserungsMenge);
		eingabePanel.add(txtBewaesserungsMenge);
		txtBewaesserungsMenge.setToolTipText("Menge des gegossenen Wassers in Liter");
		eingabePanel.add(lblDatum);
		setzeDatumTxtFeld();
		
		buttonPanel.add(btnSpeichern);
		btnSpeichern.addActionListener(this);
		buttonPanel.add(btnAbbrechen);
		btnAbbrechen.addActionListener(this);
		
		bewaesserungsFrame.getContentPane().add(infoPanel, BorderLayout.NORTH);
		bewaesserungsFrame.getContentPane().add(eingabePanel,BorderLayout.CENTER);
		bewaesserungsFrame.getContentPane().add(buttonPanel,BorderLayout.SOUTH);
		bewaesserungsFrame.pack();
		
	}
	
	private void ueberpruefeBewaesserung() {
		
		if(istBewaesserungVorhanden()){
			sb.append("Für diese Aussaat gibt es ein vorheriges Bewässerung vom ").append(bewaesserung.getDatum()).append("<br></html>");
			vorherigesDatum = bewaesserung.getDatum();
			
		}else {
			System.out.println("Noch keine Bewaesserung vorhanden");
		}
		
	}

	private boolean istBewaesserungVorhanden() {
		
		int aussaatID = Integer.parseInt(ausgewaehlteZeile.get(0));

		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("test");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("SELECT a FROM Aussaat a WHERE a.aussaatID =:ID");
				  q.setParameter("ID",aussaatID);
		Aussaat aussaat = (Aussaat) q.getSingleResult();	
		
		Bewaesserung bewaesserung = aussaat.getBewaesserung();
		em.close();
		try{	
			 /*Wenn es keinen vorherige Bewässerung für die Aussaat gibt wird hier eine Exception geworfen
			  * wenn dies geschieht wird die Exception gefangen und man weiß das es noch keine Bewässerung gibt
			  */
			bewaesserungID = bewaesserung.getBewaesserungID();
			}catch(NullPointerException e){
				bewaesserungVorhanden = false;
				return false;
			}
			
			 this.bewaesserung = bewaesserung;
			 bewaesserungVorhanden = true;
			return true;
	}

	private void setzeDatumTxtFeld() {
		
		try {
			datumFormat = new MaskFormatter("##.##.####");
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		txtDatum = new JFormattedTextField(datumFormat);
		txtDatum.setText(simpleDateFormat.format(aktuellesDatum));
		eingabePanel.add(txtDatum);
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		
		Object obj = e.getSource();
		
		if (obj == btnAbbrechen) {	
			bewaesserungsFrame.dispose();
		}
		
		/*
		 * Eingabe wird überprüft wenn alles OK ist
		 * dan wird überprüft ob die Bewässerung neu hinzugefügt oder 
		 * geupdatet werden muss.
		 * Falls die Bewässerung geupdatet werden soll wird geprüft ob nicht schon
		 * eine Bewässerung an dem gleichen Tag stattgefunden hat.
		 * Wenn dies nicht der Fall ist kann geupdatet werden, 
		 * Beim Updaten wird nochmal überprüft ob das Update
		 * nicht evtl abgebrochen wurde, weil der nutzer darauf hingewiesen
		 * wurde das die vorherige Bewässerung gelöscht wird und er das nicht möchte.
		 */

			if(obj == btnSpeichern){

				if(ueberpruefeEingabe()) {
				
					if(bewaesserungVorhanden){
						
						if(istUpdateMoeglich()){
						
							if(doUpdateBewaesserung()){
								einfügenEnde();
							}else{
								//Update abebrochen -> nix passiert
							}
						}else{
							System.out.println("Datum Fehler!");
						}
	
						
					}else{
					fuegeBewaesserungEin();
					einfügenEnde();
					}

					
				}else{
					System.out.println("Ein Fehler ist aufgetreten");
				}
			}
	}

	private boolean doUpdateBewaesserung() {		
		
		Object[] options = {"Löschen","Abbrechen"};
		int selected = JOptionPane.showOptionDialog(null,"Die vorherige Bewässerung wird überschrieben!", "ACHTUNG!", JOptionPane.YES_NO_OPTION,
			   JOptionPane.WARNING_MESSAGE, null , options ,options[1]);
		switch(selected){
			case 0:

				System.out.println("Die aktuelle Bewässerung wird überschrieben");
				EntityManagerFactory factory;
				factory = Persistence.createEntityManagerFactory("test");
				EntityManager em = factory.createEntityManager();
				em.getTransaction().begin();
	
				Query q = em.createQuery("UPDATE Bewaesserung b SET b.bewaesserungsMenge =:menge, b.datum =:datum WHERE b.bewaesserungID =:ID");
							q.setParameter("menge", bewaesserungsMengeString);
							q.setParameter("datum", datum);
							q.setParameter("ID",bewaesserungID);
							q.executeUpdate();
			  
				em.getTransaction().commit();
				em.close(); 
				return true;
	
			case 1:
				System.out.println("Update abgebrochen!");
				return false;
	
		}
		return false;


	}

	private boolean istUpdateMoeglich() {
		
		try{
			vergleicheDatum();
		}catch(InputException e){
			return false;
		}
		return true;
	}


	private void vergleicheDatum() throws InputException {
		
		String aktuellesDatumString = simpleDateFormat.format(aktuellesDatum);
		
		if(vorherigesDatum.equals(aktuellesDatumString)){
			throw new InputException("Eine Pflanze kann nur einmal pro Tag bewässert werden!");
		}
		
	}


	private void einfügenEnde() {
		
		Object[] options = {"Fertig!","Neue Bewässerung!"};
		int selected = JOptionPane.showOptionDialog(null,"Bewässerung hinzugefügt!", "Hinzufügen Erfolgreich", JOptionPane.YES_NO_OPTION,
					   JOptionPane.QUESTION_MESSAGE, null , options ,options[1]);
		
		switch(selected){
		case 0:
			bewaesserungsFrame.dispose();
			break;
		case 1:
			bewaesserungsFrame.dispose();
			new FortschrittTabellenFenster(2);
			break;
		}
		
	}


	private void fuegeBewaesserungEin() {
		
		int aussaatID = Integer.parseInt(ausgewaehlteZeile.get(0));
		EntityManagerFactory factory;
		factory = Persistence.createEntityManagerFactory("test");
		EntityManager em = factory.createEntityManager();
		em.getTransaction().begin();
		
		Query q = em.createQuery("SELECT a FROM Aussaat a WHERE a.aussaatID =:ID");
				  q.setParameter("ID",aussaatID);
		Aussaat aussaat = (Aussaat) q.getSingleResult();	
		
		Bewaesserung bewaesserung = new Bewaesserung();
		
		bewaesserung.setAussaat(aussaat);
		bewaesserung.setBewaesserungsMenge(bewaesserungsMengeString);
		bewaesserung.setDatum(datum);
		
		em.persist(aussaat);
		em.persist(bewaesserung);
		em.flush();
		em.getTransaction().commit();
		em.refresh(aussaat);
		em.refresh(bewaesserung);
		em.close();
		
	}


	private boolean ueberpruefeEingabe() {
		
		boolean pruefe = false;
		try {
			ueberpruefeDatum();
			pruefe = hohleEingabe();


		} catch (InputException e) {
			System.out.println("Eingabe Fehler");
		} catch (NumberFormatException n){
			System.out.println("Bitte Zahlen eingeben!");
			JOptionPane.showMessageDialog(null,"Bitte für die Menge nur Zahlen eingeben.","Fehler",JOptionPane.ERROR_MESSAGE);
		}
		return pruefe;
	}
	
	private void ueberpruefeDatum() throws InputException {
		hohleAussaatDatum();
		datum = txtDatum.getText();
		
		if(istDatumVerwendbar()){
			
			/*Das Aktuelle Datum wird in einen String mit dem format dd.mm.yyyy umgewandelt.
			Dan wird das aktuelle Datum wieder als Date gespeichert nur mit dem vorher definierten format
			so kann das aktuelle Datum mit dem eingegebenen Datum verglichen werden */
							
			String aktuellesDatumString = simpleDateFormat.format(aktuellesDatum);
			String[] teilString = datum.split(Pattern.quote(".")); // Das eingegebene Datum wird gesplittet
			 
			try {
				 aktuellesDatum = simpleDateFormat.parse(aktuellesDatumString);
				
			} catch (ParseException e) {
				e.printStackTrace();
			}
			
			if(eingegebenesDatum.after(aktuellesDatum)){
				throw new InputException("Das eingegebene Datum darf nicht nach dem aktuellem Datum liegen!");
				
			// Eingegebenes Datum ist ungültig wenn kein Tag, Monat oder Jahr angegeben wird bsp.: 00.00.0000	
			// um dies zu überprüfen wird der vorher gesplittete String genutzt
			}else if((teilString[0]).equals("00") || (teilString[1].equals("00") || teilString[2].equals("0000") || teilString[2].substring(0, 1).equals("0")) ){
			    throw new InputException("Das Datum muss im format tt.mm.yyyy eingegeben werden und darf nicht 0 sein");
			
			}else if(eingegebenesDatum.equals(aktuellesDatum)){
				System.out.println("Alles ok");
			}
			
		}else {
			throw new InputException("Das Datum der Bewässerung darf nicht vor dem Aussaat Datum liegen!");
		}

	
	}
		
		private boolean istDatumVerwendbar() {
			
			try {
				aussaatDate = simpleDateFormat.parse(aussaatDatum);
				eingegebenesDatum = simpleDateFormat.parse(datum);
			} catch (ParseException e) {
				e.printStackTrace();
				return false;
			}

			if(eingegebenesDatum.before(aussaatDate)){
				return false;
				
			}
			return true;
		}
	
	

		private void hohleAussaatDatum() {
			
			int aussaatID = Integer.parseInt(ausgewaehlteZeile.get(0));

			EntityManagerFactory factory;
			factory = Persistence.createEntityManagerFactory("test");
			EntityManager em = factory.createEntityManager();
			em.getTransaction().begin();
			
			Query q = em.createQuery("SELECT a FROM Aussaat a WHERE a.aussaatID =:ID");
					  q.setParameter("ID",aussaatID);
			Aussaat aussaat = (Aussaat) q.getSingleResult();	
			
			aussaatDatum = aussaat.getAussaatDatum();
			
			em.close();
		
	}

		private boolean hohleEingabe() throws InputException,NumberFormatException {
			
			bewaesserungsMenge = Double.parseDouble(txtBewaesserungsMenge.getText());
			sb.append(bewaesserungsMenge).append(" Liter");
			bewaesserungsMengeString = sb.toString();
			sb.setLength(0);

			
			if(isEingabeLeer()){
				
				throw new InputException("Eine oder mehrere Eingaben fehlen, bitte keine Negativen Zahlen angeben!");
				
			
			}else{

				return true;

			}
			
		}

		private boolean isEingabeLeer() {
			
			if(bewaesserungsMenge <= 0.0  ){
				
				return true;
			
			}else{
			
				return false;
			}
		}
}
